package com.qtrue.thread3;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

/**
 * @Package: com.qtrue.thread3
 * @ClassName: ThreadCreateNew01
 * @Author: xiaoBao
 * @CreateTime: 2022-05-14 14:37
 * @Description:创建线程的方式三：实现Callable接口。 --- JDK 5.0新增
 *
 * 如何理解实现Callable接口的方式创建多线程比实现Runnable接口创建多线程的方式强大？
 *  1. call()可以有返回值。
 *  2. call()可以抛出异常（在外部调用get()获取返回值时，可以捕获异常，获取异常中的信息）
 *  3. Callable支持泛型。
 *      3.1 写在Callable后加上泛型<>改变返回值的类型；
 *      3.2 当Callable写了泛型后，FutureTask实例化时也要加上和Callable一样的泛型<>；
 *      3.3 泛型可不写，默认返回值类型为Object。
 *
 * 例子：
 *  遍历1-100内的偶数，并且返回所有偶数的和
 */
public class ThreadCreateNew01_Callable {
    public static void main(String[] args) {
        // 3. 实例化线程类的对象
        NumThread numThread = new NumThread();

        // 4. 将此Callable接口的实现类的对象作为参数传递到FutureTask，创建FutureTask的对象。
        FutureTask futureTask = new FutureTask(numThread);

        // 5. 将FutureTask的对象作为参数传递到Thread类的构造器中，创建Thread对象，并调用start()启动线程。
        new Thread(futureTask).start();

        try {
            // 6. 获取Callable实现类中的call()的返回值（如不需要返回值此步骤可以忽略）
            // get()：返回值即为futrueTask构造器参数Callable实现类重写的call()的返回值
            Object sum = futureTask.get();
            System.out.println("总和为：" + sum);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        } catch (ExecutionException e) {
            throw new RuntimeException(e);
        }
    }
}

// 1. 创建一个实现Callable的实现类
class NumThread implements Callable{

    // 2. 实现call方法，将此线程需要执行的操作声明在call方法中
    @Override
    public Object call() throws Exception {
        int sum = 0;
        for (int i = 0;i <= 100;i++){
            if (i % 2 == 0){
                System.out.println(i);
                sum += i;
            }
        }
        return sum;
    }

}
